home *** CD-ROM | disk | FTP | other *** search
- These notes correspond to the "August 5 92 PCL" version of PCL.
-
- This version of PCL is much closer than previous versions of PCL
- to the metaobject protocol specified in "The Art of the Metaobject Protocol",
- chapters 5 and 6, by Gregor Kiczales, Jim des Riveres, and Daniel G. Bobrow.
-
-
- [Please read the file may-day-notes.text also. Most of that file still applies.]
-
- Support for structures
- You can use structure-class as a metaclass to create new classes.
- Classes created this way create and evaluate defstruct forms which
- have generated symbols for the structure accessors and constructor.
- The generated symbols are used by the primary slot-value-using-class
- methods and by the primary allocate-instance method for structures.
- Defmethod optimizes usages of slot-value (when no user-defined
- slot-value-using-class methods exist) into direct calls of the
- generated symbol accessor, which the compiler can then optimize further.
- Even when there are user-defined methods on slot-value-using-class,
- PCL does a variety of optimizations.
-
- If your implementation's version of the *-low.lisp file
- contains definitions of certain structure functions (see the end of
- low.lisp, cmu-low.lisp, lucid-low.lisp, and kcl-low.lisp), then
- structure classes are supported for all defstructs. In this case,
- structure classes are created automatically, when necessary.
-
- New Classes:
- structure-class
- structure-object
- slot-class
- slot-object
- structure-direct-slot-definition
- structure-effective-slot-definition
-
- Improvements to slot-access
- Optimization for slot-value outsize of defmethod
- Optimization for slot-value inside of defmethod, but not of a specialized parameter.
- Optimizations that work even when there are :around methods
- on slot-value-using-class.
-
- New types:
- `(class ,class-object)
- `(class-eq ,class-object)
-
- New specializer class: class-eq-specializer
- Every class has a class-eq specializer which represents all
- the direct instances of that class.
- This is useful in *subtypep. For example, here is the way
- generic-function initialization checks that the method-class is valid:
- (and (classp method-class)
- (*subtypep (class-eq-specializer method-class)
- (find-class 'standard-method)))
- If you want to define methods having class-eq specializers,
- see "Initialization of method metaobjects". The default behavior of PCL
- is to disallow this.
-
- compute-applicable-methods-using-types
-
- caching improvements
-
- no magic-generic-functions list
- This simplifies some things, but complicates some other things.
- I wanted to support user-defined classes which are their own metaclass.
- You can now do:
- (defclass y (standard-class) ())
- (defmethod validate-superclass ((c y) (sc standard-class)) t)
- (defclass y (standard-class) () (:metaclass y))
-
- method-function changes (see the comments for make-method-lambda, below)
-
- final dfuns
-
- -------------------------
-
- gfs which obey AMOP ch 6
- accessor-method-slot-definition
- add-dependent
- add-direct-method
- add-direct-subclass
- add-method
- allocate-instance
- compute-class-precedence-list
- compute-default-initargs
- compute-discriminating-function
- compute-effective-slot-definition
- [Note: compute-effective-slot-definition relys on
- compute-effective-slot-definition-initargs and effective-slot-definition-class.
- compute-effective-slot-definition-initargs is quite useful, but is not in
- AMOP ch 6.]
- compute-slots
- direct-slot-definition-class
- effective-slot-definition-class
- ensure-class
- ensure-class-using-class
- ensure-generic-function
- ensure-generic-function-using-class
- eql-specializer-object
- extract-lambda-list
- extract-specializer-names
- finalize-inheritance
- find-method-combination
- funcallable-standard-instance-access
- {generic-function-method-class, generic-function-method-combination,
- generic-function-lambda-list, generic-function-methods, generic-function-name}
- intern-eql-specializer
- make-instance
- make-method-lambda
- map-dependents
- {method-function, method-generic-function, method-lambda-list,
- method-specializers, method-qualifiers}
- {class-default-initargs, class-direct-default-initargs, class-direct-slots,
- class-direct-subclasses, class-direct-superclasses, class-finalized-p,
- class-name, class-precedence-list, class-prototype, class-slots}
- {slot-definition-allocation, slot-definition-initargs, slot-definition-initform,
- slot-definition-initfunction, slot-definition-name, slot-definition-type}
- {slot-definition-readers, slot-definition-writers}
- {slot-definition-location}
- remove-dependent
- remove-direct-method
- remove-direct-subclass
- remove-method
- set-funcallable-instance-function
- (setf slot-value-using-class)
- slot-boundp-using-class
- slot-makunbound-using-class
- specializer-direct-generic-functions
- specializer-direct-methods
- standard-instance-access
- update-dependent
-
- gfs which DO NOT obey AMOP ch 6
-
- compute-applicable-methods
- compute-applicable-methods-using-classes
- Handles class-eq specializers without signalling an error.
- But see "Initialization of method metaobjects", below.
-
- compute-effective-method
- Returns only one value.
-
- generic-function-argument-precedence-order
- Not yet defined. Can get this information from the arg-info structure.
-
- generic-function-declarations
- Not yet defined.
-
- reader-method-class
- Not yet defined. Some bootstrapping considerations are involved,
- but adding this will not be very hard.
-
- (setf class-name)
- Currently just a writer method. Does not call reinitialize-instance or
- (setf find-class).
-
- (setf generic-function-name)
- Currently just a writer method. Does not call reinitialize-instance.
-
- writer-method-class
- Not yet defined. Some bootstrapping considerations are involved,
- but adding this will not be very hard.
-
- ---------------------------
-
- Initialization of method metaobjects
- The following methods are defined:
- legal-qualifiers-p (method standard-method) qualifiers
- legal-lambda-list-p (method standard-method) lambda-list
- legal-specializers-p (method standard-method) specializers
- legal-method-function-p (method standard-method) function
- legal-documentation-p (method standard-method) documentation
-
- legal-specializer-p (method standard-method) specializer
-
- You can override them if you want.
- The method for legal-specializers-p calls legal-specializer-p
- on each specializer.
- The method for legal-specializer-p allows any kind of specializer
- when the variable *allow-experimental-specializers-p* is t
- (this variable is initially nil).
-
- ---------------------------
- Optimizations on slot-value
- Outside of a defmethod when define-compiler-macro is not implemented
- or the slot-name is not constant, or
- Inside a defmethod when the slot-name is not a constant:
- (1) no optimization of slot-value, slot-value-using-class is called.
- slot-value-using-class has a special dfun, though, which calls
- the slot's slot-definition-reader-function. This function is
- a result of get-accessor-method-function.
- Outside of a defmethod when define-compiler-macro is implemented and
- the slot-name is a constant, or
- Inside a defmethod when the slot-name is a constant but the object is
- not either (the value of a parameter specialized to a subclass of structure-object
- for which no user-defined slot-value-using-class methods apply at defmethod time),
- or (the value of a parameter specialized to a subclass of standard-object).
- (2) PCL arranges to call an automatically created generic function
- which has one method: a reader method defined on class slot-object.
- Inside a defmethod when the slot-name is a constant and the object
- is (the value of a parameter specialized to a subclass of structure-object
- for which no user-defined slot-value-using-class methods apply).
- (3) The slot-value form is converted to a call of the structure slot's
- accessor function, which the compiler can then optimize further.
- Inside a defmethod when the slot-name is a constant and the object
- is (the value of a parameter specialized to a subclass of standard-object).
- (4) The access requires two arefs, a call to (typep x 'fixnum), and a call to eq,
- in the best case. If user defined slot-value-using-class methods apply
- at slot-value execution time, or the slot is unbound, the unoptimized
- slot-value function (1) is called. This was in May Day PCL; what is new here
- is that the PV (permutation vector) is looked up at defmethod load time
- rather than at run time, if the effective method is cached.
-
- Generic functions containing only accessor methods for which no user-defined
- methods on slot-value-using-class apply and which involve only standard-classes:
- A special dfun is called: one-class, two-class, one-index, or n-n.
- These were all in May Day PCL.
- Generic functions excluded by the above, which contain accessor methods:
- In place of each accessor method's method-function, a function returned by
- get-accessor-method-function is used.
-
- get-accessor-method-function (gf type class slotd) ; type is reader, writer, or boundp.
- If there is only one applicable method,
- (This method will be the system supplied one)
- the function that is returned is optimized for the current state of the
- class. When the class changes, it must be recomputed.
- otherwise,
- a secondary dispatch function for slot-value-using-class is computed
- (using what is known about the types of the arguments) and converted
- into an accessor function.
-
- get-secondary-dispatch-function (gf methods types &optional method-alist wrappers)
- The types argument describes what is known about the types of the arguments.
- Method-alist is used (when supplied) to do things like replace the
- standard slot-value-using-class method function with a function optimized
- for what is known about the arguments.
- Wrappers (when supplied) means that the resulting function is guaranteed to
- be called only whith those wrappers. Make-effective-method-function calls
- the generic-function method-function-for-caching with method-alist and
- wrappers to get a optimized method function. (PV lookup is done at the time
- method-function-for-caching is called).
-
- compute-applicable-methods: Here I tried to stick with the MOP.
- The function cache-miss-values looks at the second value of the result of
- compute-applicable-methods-using-classes. If this value is null, we aren't
- supposed to cache the result of camuc. So we don't. Instead we cache a
- result of (default-secondary-dispatch-function gf), which in turn calls
- compute-applicable-methods each time it is called.
- ---------------------------
-
- To do:
-
- Problem: sometimes there is no need to call a gf's dfun: the emf that is invoked
- can be cached in the caller's method closure.
- 1. In expand-defmethod-internal, optimize calls to generic-functions.
- Add the support for this optimization.
-
- 2. [When CMUCL improves its setf handling, remove the comment in
- the file macros.lisp beginning the line ";#+cmu (pushnew :setf *features*)"]
-
-
-
- --------------
- 1) Generalize expand-defmethod-internal so that it can be used for non-defmethod
- code. Maybe by (a) having a parameter that says whether it is being called by
- defmethod, and (b) using the techniques used by the series package (shadowing
- defun and some others, making the shadowed definitions call e-d-i, making it
- easy for people to do the relevant package modifications)
-
- 2) Extending generic-functions by allowing the user at defgeneric time to supply
- the name of a function which will be supplied (by the system) with a definition
- which will return equivalent results to those returned by the generic function,
- but which will (in some cases) have less checking than the generic function.
- One-class, two-class, and one-index gf dfuns will map to a result of
- get-optimized-std-accessor-method-function, checking gf dfuns will map to their
- function, and any other dfun will remain the same.
-
- 3) Extending expand-defmethod-internal to optimize calls to generic-functions.
- There are a variety of possibilities that need to be considered; one of them
- will be to arrange to call the optimized functions produced by (2) when it
- is known to be safe.
- ----------------------------------------------------------------------
- ----------------------------------------------------------------------
-
- Here is how PCL uses the compiler at run time:
-
- The only function that uses COMPILE is COMPILE-LAMBDA, defined in
- low.lisp. See the code for some comments on how it works.
-
- There are basically three uses of COMPILE-LAMBDA:
- for creating discriminator functions (March 92 PCL creates discriminator
- functions via lap code, September 16 PCL creates lisp code directly -
- it is easier to read the Sept PCL code. Both versions invoke
- COMPILE-LAMBDA in a similar manner.) Precompiling of discriminator
- functions is done via the macro precompile-dfun-constructors.
- for creating constructor functions (This is in Sept PCL only;
- see fast-init.lisp for more information). Precompiling of
- constructor functions is done via the macro precompile-iis-functions.
- for creating the internal functions used by GET-FUNCTION (defined in
- fngen.lisp. Refer to the September 16 92 PCL version because it has
- better documentation on GET-FUNCTION.) Precompiling of these functions
- is done by precompile-function-generators.
-
- Precompiling of all three kinds of functions is done by
- PRECOMPILILE-RANDOM-CODE-SEGMENTS (defined in low.lisp).
-
- There are two uses of GET-FUNCTION (actually GET-FUNCTION1):
- to create effective-method-functions, which are the functions which
- actually call methods. Every method referred to by aan
- effective-method-function is an applicable method as determined by
- COMPUTE-APPLICABLE-METHODS (or maybe -USING-CLASSES or
- -USING-TYPES). See the file combin.lisp.
- to create secondary dispatch functions. These functions are called by
- discriminator functions when the dfun couldn't determine the set of
- applicable methods (when EQL specializers are present), and are
- actually discriminator functions in themselves sometimes (these
- are called dispatch dfuns). See the file methods.lisp.
-